package com.example.tool.web.expressdeliveryl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.tool.bean.business.wdt.LogisticsTrajectoryDO;
import com.example.tool.service.RedisService;
import com.example.tool.service.logisticstrajectory.LogisticsTrajectoryService;
import com.example.tool.util.DateUtil;
import com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryResult;
import com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryTrack;
import com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryUtil;
import com.example.tool.util.ems.EMSApiUtil;
import com.example.tool.util.yto.bean.UpdateInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.StringReader;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.example.tool.conf.WarehouseMsgConfig.collectionDelayKeyTemplate;
import static com.example.tool.conf.WarehouseMsgConfig.transferTimeoutAfterKeyTemplate;
import static com.example.tool.conf.WarehouseMsgConfig.transferTimeoutKeyTemplate;
import static com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryUtil.EMS;
import static com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryUtil.JT;
import static com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryUtil.STO;
import static com.example.tool.util.ExpressDeliveryUtil.ExpressDeliveryUtil.YUN_DA;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.RECEIVED;
import static com.example.tool.util.ExpressDeliveryUtil.TrackTypeEnum.SENDER;

@RestController
//@CrossOrigin(origins = "*")
@RequestMapping("/tool/expressDelivery")
public class ExpressDeliveryController {
    @Autowired
    private LogisticsTrajectoryService logisticsTrajectoryService;
    @Autowired
    private RedisService redisService;

    /**
     * 中通 o
     *
     * @param response
     * @param ztoTrajectory
     */
    @PostMapping("/ztoTrajectory")
    public void ztoTrajectory(HttpServletResponse response, @RequestParam Map<String, String> ztoTrajectory) {
//        System.out.println("ztoTrajectory:"+ztoTrajectory);
        if (ztoTrajectory.containsKey("data")) {
            LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();

            JSONObject param = JSONObject.parseObject(ztoTrajectory.get("data"));
            if (param.containsKey("billCode")) {
                logisticsTrajectoryDO.setProgressInfo(param.toString());
                String waybillNo = param.getString("billCode");
                logisticsTrajectoryDO.setLogisticsNo(waybillNo);
                ExpressDeliveryResult result = ExpressDeliveryUtil.queryLogistics(waybillNo);
                Boolean succeed = result.getSucceed();
                if (succeed) {
                    logisticsMonitoring(result);
                }
            }
            logisticsTrajectoryService.save(logisticsTrajectoryDO);
        }
//        String action = param.getString("action");
//        Date actionTime= DateUtil.toDate(param.getString("actionTime"));
//        System.out.println(param.toJSONString());
//        LogisticsTrajectoryDO item = new LogisticsTrajectoryDO();
//        item.setLogisticsType(ZTO);
////        item.setLogisticsNo();
//        item.setProgressInfo(ztoTrajectory.toString());
//        logisticsTrajectoryService.save(item);
//        System.out.println(ztoTrajectory);


    }

    public void logisticsMonitoring(ExpressDeliveryResult result) {
        //        if (succeed){
        List<ExpressDeliveryTrack> tracks = result.getTracks();
        if (tracks.isEmpty()) {
            return;
        }
        ExpressDeliveryTrack track = tracks.get(tracks.size() - 1);
        String logisticsNo = result.getWaybillNo();
        String scanType = track.getScanType();
//            Boolean isCenter = track.getIsCenter();
//            Boolean isTransfer = track.getIsTransfer();
//            String desc = track.getDesc();
        Date now = new Date();
        Date scanDate = track.getScanDate();
//            Date outTime =null;
        //        }
        /**
         * 揽收超时 发货后超过24小时未揽收
         * 中转超时 揽收后 一直到中转每个步骤 超过24小时不更新 都算
         * 中转后物流异常  第一次到了中转以后每次物流超过24小时不更新
         *
         * 状态是
         * 揽收 删除揽收超时KEY  储存 中转超时
         * 发送中转   删除原来中转超时key 保存新的中转超时key
         * 抵达中转   删除中转超时key  设置物流异常的key
         * 。。      删除原来物流异常的key 保存新的物流异常的key
         * 签收（结束不判断）删除所有key
         *
         * 设置过期时间为 24小时 到期后判断是否未到中转站
         * 并删除揽收超时KEY
         *
         * 到中转设置
         * 判断是否是揽收 揽收判断揽收超时
         *
         */
//            String transferTimeoutKey="";
//            String transferTimeoutAfterKey="";
//            String collectionDelayKey="";
        Long timeDifference = 0L;
        switch (scanType) {
            case "NOT_COLLECTED":
                break;//未知
            case "COLLECTION":
//                    collectionDelayKey=String.format(collectionDelayKeyTemplate,logisticsNo);
                redisService.delete(String.format(collectionDelayKeyTemplate, logisticsNo));
//                    transferTimeoutAfterKey=String.format(transferTimeoutKeyTemplate,logisticsNo);
                timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                redisService.setWithExpire(String.format(transferTimeoutKeyTemplate, logisticsNo), "", timeDifference, TimeUnit.SECONDS);
                break;//揽收
            case "SENDER":
            case "RECEIVED":
                //判断是否第一次发完或者到达中转站
           /*         long count = tracks.stream().filter(e->e.getIsTransfer()&& ObjectUtil.equal(e.getScanType(),scanType)).count();
                    if (count>1){
                        redisService.delete(String.format(collectionDelayKeyTemplate,logisticsNo));
                        redisService.delete(String.format(transferTimeoutKeyTemplate,logisticsNo));
                        redisService.delete(String.format(transferTimeoutAfterKeyTemplate,logisticsNo));
                        timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                        redisService.setWithExpire(String.format(transferTimeoutAfterKeyTemplate,logisticsNo),"",timeDifference, TimeUnit.SECONDS);
                    }else {
//                        collectionDelayKey=String.format(collectionDelayKeyTemplate,logisticsNo);
                        redisService.delete(String.format(collectionDelayKeyTemplate,logisticsNo));
//                        transferTimeoutAfterKey=String.format(transferTimeoutKeyTemplate,logisticsNo);
                        timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                        redisService.setWithExpire(String.format(transferTimeoutKeyTemplate,logisticsNo),"",
                        timeDifference, TimeUnit.SECONDS);
                    }*/


                //判断是否第一次发完或者到达中转站
                long toTransitNum = tracks.stream().filter(e -> e.getIsTransfer() && ObjectUtil.equal(e.getScanType(), RECEIVED.getCode())).count();
                if (ObjectUtil.equal(scanType, SENDER.getCode())) {//发件
                    if (toTransitNum == 0) {//第一次 发往中转站 跳过
                        return;
                    }
                    //不是第一次发中转站 设置物流异常key
                    redisService.delete(String.format(transferTimeoutAfterKeyTemplate, logisticsNo));
                    timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                    redisService.setWithExpire(String.format(transferTimeoutAfterKeyTemplate, logisticsNo), "", timeDifference, TimeUnit.SECONDS);
                } else {//到件
                    if (toTransitNum == 1) {//第一次到中转站
                        redisService.delete(String.format(transferTimeoutKeyTemplate, logisticsNo));
                        timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                        redisService.setWithExpire(String.format(transferTimeoutAfterKeyTemplate, logisticsNo), "", timeDifference, TimeUnit.SECONDS);
                    } else {//不是第一次到中转站
                        redisService.delete(String.format(transferTimeoutAfterKeyTemplate, logisticsNo));
                        timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                        redisService.setWithExpire(String.format(transferTimeoutAfterKeyTemplate, logisticsNo), "", timeDifference, TimeUnit.SECONDS);
                    }


                }


                break;//到件
            case "DELIVERY"://派件
            case "ARRIVAL"://代收
            case "TRANSFER_ORDER"://转单
            case "GIVEBACK"://退回
//                    collectionDelayKey=String.format(transferTimeoutKeyTemplate,logisticsNo);
                redisService.delete(String.format(transferTimeoutKeyTemplate, logisticsNo));
//                    collectionDelayKey=String.format(transferTimeoutAfterKeyTemplate,logisticsNo);
                redisService.delete(String.format(transferTimeoutAfterKeyTemplate, logisticsNo));
//                    transferTimeoutAfterKey=String.format(transferTimeoutAfterKeyTemplate,logisticsNo);
                timeDifference = DateUtil.findTimeDifference(now, DateUtil.addHourDate(scanDate, 24));
                redisService.setWithExpire(String.format(transferTimeoutAfterKeyTemplate, logisticsNo), "", timeDifference, TimeUnit.SECONDS);
                break;
            case "SIGNED":
//                     transferTimeoutAfterKey=String.format(transferTimeoutAfterKeyTemplate,logisticsNo);
                //                 redisService.delete(collectionDelayKey);
                redisService.delete(String.format(transferTimeoutAfterKeyTemplate, logisticsNo));
                break;//签收
        }


    }

    /**
     * 圆通 ?
     *
     * @param logisticsInterface
     */
    @PostMapping(value = "/ytoTrajectory",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_XML_VALUE)
    public String ytoTrajectory(@RequestParam("logistics_interface") String logisticsInterface) {
        try {

            UpdateInfo updateInfo = (UpdateInfo) JAXBContext.newInstance(UpdateInfo.class)
                    .createUnmarshaller().unmarshal(new StringReader(logisticsInterface));
            LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();
            logisticsTrajectoryDO.setProgressInfo(updateInfo.toString());
            System.out.println("ytoTrajectory:" + updateInfo);
            String waybillNo = updateInfo.getMailNo();
            logisticsTrajectoryDO.setLogisticsNo(waybillNo);
            logisticsTrajectoryService.save(logisticsTrajectoryDO);
            if (StringUtils.isNotBlank(waybillNo)) {
                ExpressDeliveryResult result = ExpressDeliveryUtil.queryLogistics(waybillNo);
                Boolean succeed = result.getSucceed();
                if (succeed) {
                    logisticsMonitoring(result);
                }
            }
            return String.format("<Response><logisticProviderID>YTO</logisticProviderID><txLogisticID>%s</txLogisticID><success>true</success></Response>", waybillNo);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 韵达 o
     */
    @GetMapping(value = "/yunDaTrajectory")
    public String yunDaTrajectory() {
        return "success";
    }

    /**
     * 韵达 o
     *
     * @param response
     * @param yunDaTrajectory
     */
    @PostMapping("/yunDaTrajectory")
    public JSONObject yunDaTrajectory(HttpServletResponse response, @RequestBody Map<String, String> yunDaTrajectory) {
//        System.out.println("yunDaTrajectory:"+yunDaTrajectory);
        String orderid = "";
        if (yunDaTrajectory.containsKey("data")) {
            JSONObject rqeData = JSONObject.parseObject(yunDaTrajectory.get("data"));
            LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();
            logisticsTrajectoryDO.setLogisticsType(YUN_DA);
            logisticsTrajectoryDO.setProgressInfo(rqeData.toString());
            String waybillNo = rqeData.getString("mailno");
            logisticsTrajectoryDO.setLogisticsNo(waybillNo);
            ExpressDeliveryResult eResult = ExpressDeliveryUtil.queryLogistics(waybillNo);
            Boolean succeed = eResult.getSucceed();
            if (succeed) {
                logisticsMonitoring(eResult);
            }
            orderid = rqeData.getString("orderid");
            logisticsTrajectoryService.save(logisticsTrajectoryDO);

        }

        JSONObject result = new JSONObject();
        result.put("result", true);
        result.put("code", "0000");
        result.put("message", "接收成功");
        JSONObject data = new JSONObject();
        data.put("orderid", orderid);
        result.put("data", data);
        return result;
    }

    /**
     * 极兔 o
     *
     * @param response
     * @param jtTrajectory
     */
    @PostMapping("/jtTrajectory")
    public JSONObject jtTrajectory(HttpServletResponse response, @RequestParam Map<String, String> jtTrajectory) {
//        System.out.println("jtTrajectory:"+jtTrajectory);
        LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();
        logisticsTrajectoryDO.setLogisticsType(JT);
        logisticsTrajectoryDO.setProgressInfo(jtTrajectory.toString());
        if (jtTrajectory.containsKey("bizContent")) {
            JSONObject bizContent = JSONObject.parseObject(jtTrajectory.get("bizContent"));
            String waybillNo = bizContent.getString("billCode");
            logisticsTrajectoryDO.setLogisticsNo(waybillNo);
            ExpressDeliveryResult eResult = ExpressDeliveryUtil.queryLogistics(waybillNo);
            Boolean succeed = eResult.getSucceed();
            if (succeed) {
                logisticsMonitoring(eResult);
            }
        }


        logisticsTrajectoryService.save(logisticsTrajectoryDO);
        JSONObject result = new JSONObject();
        result.put("code", 1);
        result.put("msg", "success");
        result.put("data", "SUCCESS");
        return result;
    }

    /**
     * ems o
     *
     * @param response
     * @param emdDaTrajectory
     */
    @PostMapping("/emsTrajectory")
    public JSONObject emsTrajectory(HttpServletResponse response, @RequestBody JSONObject emdDaTrajectory) {
        System.out.println("emdDaTrajectory:" + emdDaTrajectory);
        LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();
        logisticsTrajectoryDO.setLogisticsType(EMS);
        logisticsTrajectoryDO.setProgressInfo(emdDaTrajectory.toString());

        if (emdDaTrajectory.containsKey("logitcsInterface")) {
            JSONObject data = JSONObject.parseObject(EMSApiUtil.sm4Decrypt(emdDaTrajectory.getString("logitcsInterface")));
            if (data.containsKey("waybillNo")) {
                String waybillNo = data.getString("waybillNo");
                logisticsTrajectoryDO.setLogisticsNo(waybillNo);
                ExpressDeliveryResult eResult = ExpressDeliveryUtil.queryLogistics(waybillNo);
                Boolean succeed = eResult.getSucceed();
                if (succeed) {
                    logisticsMonitoring(eResult);
                }
            }
            logisticsTrajectoryService.save(logisticsTrajectoryDO);
        }
        JSONObject result = new JSONObject();
        result.put("serialNo", emdDaTrajectory.getString("serialNo"));
        result.put("code", "00000");
        result.put("codeMessage", "客户自行提供");
        result.put("senderNo", emdDaTrajectory.getString("senderNo"));
        return result;
    }

    /**
     * 申通 o
     *
     * @param response
     * @param stoTrajectory
     */
    @PostMapping("/stoTrajectory")
    public void stoTrajectory(HttpServletResponse response, @RequestParam Map<String, String> stoTrajectory) {
//         System.out.println("stoTrajectory:"+stoTrajectory);
        if (ObjectUtil.isNotNull(stoTrajectory)) {
            LogisticsTrajectoryDO logisticsTrajectoryDO = new LogisticsTrajectoryDO();
            logisticsTrajectoryDO.setLogisticsType(STO);
            logisticsTrajectoryDO.setProgressInfo(stoTrajectory.toString());
            JSONObject content = JSONObject.parseObject(stoTrajectory.get("content"));
            if (content.containsKey("waybillNo")) {
                String waybillNo = content.getString("waybillNo");
                logisticsTrajectoryDO.setLogisticsNo(waybillNo);
                ExpressDeliveryResult eResult = ExpressDeliveryUtil.queryLogistics(waybillNo);
                Boolean succeed = eResult.getSucceed();
                if (succeed) {
                    logisticsMonitoring(eResult);
                }
            }
            logisticsTrajectoryService.save(logisticsTrajectoryDO);
        }

    }

    /**
     * 申通 o
     *
     * @param response
     * @param cainiaoTrajectory
     */
    @PostMapping("/cainiaoTrajectory")
    public void cainiaoTrajectory(HttpServletResponse response, @RequestParam Map<String, String> cainiaoTrajectory) {
        System.out.println(cainiaoTrajectory);
    }

}
